mod planner;
use crate::sql::parse::ast;
use crate::sql::parse::ast::Expression;
use crate::sql::plan::planner::Planner;
use crate::sql::schema::Table;

#[derive(Debug)]
pub enum Node {
    CreateTable {
        schema: Table
    },
    Insert {
        table_name: String,
        columns: Vec<String>,
        values: Vec<Vec<Expression>>
    },
    Scan {
        table_name: String
    }
}

//执行计划定义，底层是不同类型执行的节点
#[derive(Debug)]
pub struct Plan(pub Node);

impl Plan {
    pub fn build(stat: ast::Statement) -> Self {
        Planner::new().build(stat)
    }
}

#[cfg(test)]
mod tests {
    use crate::error::Result;
    use crate::sql::parse::Parse;
    use crate::sql::plan::Plan;

    #[test]
    fn test_plan_create_table() -> Result<()> {
        let sql = "
            create table table1 (
                a int default 100,
                b float not null,
                c varchar null,
                d bool default true
            );
        ";
        let ast = Parse::new(sql).parse()?;
        println!("{:?}", ast);
        let plan = Plan::build(ast);
        println!("{:?}", plan);
        Ok(())
    }

    #[test]
    fn test_plan_insert() -> Result<()> {
        let sql = "
            insert into tab1 values (1, 2, 3, 'a', true);
        ";
        let ast = Parse::new(sql).parse()?;
        println!("{:?}", ast);
        let plan1 = Plan::build(ast);
        println!("{:?}", plan1);


        let sql2 = "
            insert into tab1 (col1, col2, col3, col4, col5) values (1, 2, 3, 'a', true);
        ";
        let ast2 = Parse::new(sql2).parse()?;
        println!("{:?}", ast2);
        let plan2 = Plan::build(ast2);
        println!("{:?}", plan2);


        let sql3 = "
            insert into tab1 (col1, col2, col3, col4, col5) values (1, 2, 3, 'a', true), (4, 5, 6, 'b', false);
        ";
        let ast3 = Parse::new(sql3).parse()?;
        println!("{:?}", ast3);
        let plan3 = Plan::build(ast3);
        println!("{:?}", plan3);


        Ok(())
    }

    #[test]
    fn test_parse_select() -> Result<()> {
        let sql = "
            select * from tab1;
        ";
        let ast = Parse::new(sql).parse()?;
        println!("{:?}", ast);
        let plan = Plan::build(ast);
        println!("{:?}", plan);


        Ok(())
    }

}